package com.obj.commpont.common.utils;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.security.SecureRandom;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * uuid工具类
 */
public class UUIDUtils {

    private static boolean noCase = false;
    private static String instanceId;
    private static AtomicInteger counter;

    private UUIDUtils() {
    }

    static {
        // 1. Machine ID - 根据IP/MAC区分
        byte[] machineId = getLocalHostAddress();

        // 2. JVM ID - 根据启动时间区分 + 随机数
        byte[] jvmId = getRandomizedTime();

        instanceId = HexUtils.bytesToString(machineId, noCase) + HexUtils.bytesToString(jvmId, noCase);

        // counter
        counter = new AtomicInteger();

        //noCase = noCase;
    }

    /**
     * 取得local host的地址，如果有可能，取得物理MAC地址。
     */
    private static byte[] getLocalHostAddress() {
        Method getHardwareAddress;

        try {
            getHardwareAddress = NetworkInterface.class.getMethod("getHardwareAddress");
        } catch (Exception e) {
            getHardwareAddress = null;
        }

        byte[] addr;

        try {
            InetAddress localHost = InetAddress.getLocalHost();

            if (getHardwareAddress != null) {
                // maybe null
                addr = (byte[]) getHardwareAddress.invoke(NetworkInterface.getByInetAddress(localHost));
            } else {
                addr = localHost.getAddress();
            }
        } catch (Exception e) {
            addr = null;
        }

        if (addr == null) {
            addr = new byte[]{127, 0, 0, 1};
        }

        return addr;
    }

    /**
     * 取得当前时间，加上随机数。
     */
    private static byte[] getRandomizedTime() {
        long jvmId = System.currentTimeMillis();
        long random = new SecureRandom().nextLong();

        // 取得上述ID的bytes，并转化成字符串
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);

        try {
            dos.writeLong(jvmId);
            dos.writeLong(random);
        } catch (Exception e) {
            //ignor exception
        }

        return baos.toByteArray();
    }

    /**
     * 创建一个随机的UUID，不具有顺序，根据机器ID、虚拟机ID、时间戳、原子数进行构建，可保证唯一
     *
     * @return uuid
     */
    public static String nextID() {
        // MACHINE_ID + JVM_ID + 当前时间 + counter
        return instanceId + HexUtils.longToString(System.currentTimeMillis(), noCase)
                + HexUtils.longToString(counter.getAndIncrement(), noCase);
    }

    /**
     * 返回uuid的16进制的表达方式
     *
     * @return 返回长度为8的16进制id，不适合作为业务主键，可用于需要短ID的业务场景
     */
    public static String nextHexId() {
        String uuid = nextID();
        return Integer.toHexString(uuid.hashCode());
    }

    /**
     * 获得一个UUID
     *
     * @return String UUID
     */
    public static String getUUID() {
        String uuid = UUID.randomUUID().toString();
        //去掉“-”符号
        return uuid.replaceAll("-", "");
    }
}
